using System;
using System.Configuration;

namespace com.bodurov.CameraToJpegFilesUI
{
    public abstract class BaseConfig
    {
        protected virtual string Prefix { get { return ""; } }

        protected void Initialize()
        {
            foreach (var property in this.GetType().GetProperties())
            {
                if (property.CanWrite)
                {
                    var foundAttr = false;
                    string stringValue = null;
                    foreach (ConfigValueAttribute attr in property.GetCustomAttributes(typeof(ConfigValueAttribute), true))
                    {
                        foundAttr = true;
                        stringValue = ConfigurationManager.AppSettings[attr.Key ?? (Prefix + property.Name)] ??
                                      Convert.ToString(attr.Default);
                        break;
                    }
                    if(!foundAttr)
                    {
                        stringValue = ConfigurationManager.AppSettings[Prefix + property.Name];
                    }
                    
                    object value;
                    if (stringValue != null && TryParse(stringValue, property.PropertyType, out value)) property.SetValue(this, value, null);
                }
            }
        }

        private delegate bool TryParseDelegate<T>(string val, out T result);

        private static bool TryParse(string stringValue, Type type, out object value)
        {
            value = null;
            if (type == typeof(string))
            {
                value = stringValue;
                return true;
            }
            if (type == typeof(int)) return TryParse<int>(stringValue, Int32.TryParse, out value);
            if (type == typeof(bool)) return TryParse<bool>(stringValue, Boolean.TryParse, out value);
            if (type == typeof(double)) return TryParse<double>(stringValue, Double.TryParse, out value);
            if (type == typeof(Guid)) return TryParse<Guid>(stringValue, Guid.TryParse, out value);
            if (type == typeof(Char)) return TryParse<char>(stringValue, Char.TryParse, out value);

            try
            {
                value = Convert.ChangeType(value, type);
                return true;
            }
            catch (Exception)
            {
                value = null;
                return false;
            }
        }
        private static bool TryParse<T>(string stringValue, TryParseDelegate<T> func, out object value)
        {
            T x;
            var r = func(stringValue, out x);
            if (r) value = x;
            else value = null;
            return r;
        }

    }
}